﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

using System.Windows;
using System.Windows.Media;
using System.Runtime.InteropServices;
using System.Windows.Interop;
using System.Security.Cryptography;
using System.Diagnostics;
using System.Threading.Tasks;
using System.Text.RegularExpressions;
using MineLaunch.Setting;

namespace MineLaunch.Common
{
	public class Common
	{
		private static char[] invaildFileNameChars = Path.GetInvalidFileNameChars();
		/// <summary>
		/// ファイル名が使用可能か確認する
		/// </summary>
		/// <param name="filename">ファイル名</param>
		/// <returns>使用可能かどうか</returns>
		public static bool CanUseFileName(string filename)
		{
			return filename.IndexOfAny(invaildFileNameChars) < 0;
		}

		/// <summary>
		/// フォルダをコピーする
		/// </summary>
		/// <param name="sourcePath">コピー元パス</param>
		/// <param name="targetPath">コピー先パス</param>
		/// <param name="isOverwrite">上書きするかどうか</param>
		public static void CopyDirectory(string sourcePath, string targetPath, bool isOverwrite)
		{
			if (!Directory.Exists(targetPath))
			{
				Directory.CreateDirectory(targetPath);
				File.SetAttributes(targetPath, File.GetAttributes(sourcePath));
				isOverwrite = true;
			}
			if (isOverwrite)
			{
				foreach (string directorySource in Directory.GetFiles(sourcePath))
				{
					string directoryTarget = Path.Combine(targetPath, Path.GetFileName(directorySource));
					File.Copy(directorySource, directoryTarget, true);
				}
			}
			else
			{
				foreach (string directorySource in Directory.GetFiles(sourcePath))
				{
					string directoryTarget = Path.Combine(targetPath, Path.GetFileName(directorySource));

					if (!File.Exists(directoryTarget))
					{
						File.Copy(directorySource, directoryTarget, false);
					}
				}
			}
			foreach (string directorySource in Directory.GetDirectories(sourcePath))
			{
				string directoryTarget = Path.Combine(targetPath, Path.GetFileName(directorySource));
				CopyDirectory(directorySource, directoryTarget, isOverwrite);
			}
		}

		/// <summary>
		/// マウスの位置を取得する
		/// </summary>
		/// <param name="v">取得する要素</param>
		/// <returns>マウスの位置</returns>
		public static Point GetMousePosition(Visual v)
		{
			Win32API.POINT p;
			Win32API.GetCursorPos(out p);
			var source = HwndSource.FromVisual(v) as HwndSource;
			Win32API.ScreenToClient(source.Handle, ref p);
			return new Point(p.X, p.Y);
		}

		/// <summary>
		/// 文字列を暗号化する
		/// </summary>
		/// <param name="source">暗号化する文字列</param>
		/// <returns>暗号化された文字</returns>
		public static string Encrypt(string source)
		{
			string password = "454759F7-FB29-4F12-8350-698007904B92";
			var rijndael = new RijndaelManaged();
			byte[] key, iv;
			GenerateKeyFromPassword(password, rijndael.KeySize, out key, rijndael.BlockSize, out iv);
			rijndael.Key = key;
			rijndael.IV = iv;

			byte[] strBytes = Encoding.UTF8.GetBytes(source);
			byte[] encBytes;
			using (var encryptor = rijndael.CreateEncryptor())
			{
				encBytes = encryptor.TransformFinalBlock(strBytes, 0, strBytes.Length);
			}
			return Convert.ToBase64String(encBytes);
		}

		/// <summary>
		/// 文字列を復号化する
		/// </summary>
		/// <param name="sourceString">復号化する文字列</param>
		/// <returns>復号化された文字列</returns>
		public static string Decrypt(string sourceString)
		{
			string password = "454759F7-FB29-4F12-8350-698007904B92";
			var rijndael = new RijndaelManaged();
			byte[] key, iv;
			GenerateKeyFromPassword(password, rijndael.KeySize, out key, rijndael.BlockSize, out iv);
			rijndael.Key = key;
			rijndael.IV = iv;

			byte[] strBytes = Convert.FromBase64String(sourceString);
			byte[] decBytes;
			using (var decryptor = rijndael.CreateDecryptor())
			{
				decBytes = decryptor.TransformFinalBlock(strBytes, 0, strBytes.Length);
			}
			return Encoding.UTF8.GetString(decBytes);
		}

		/// <summary>
		/// パスワードからキーとベクターを生成する
		/// </summary>
		/// <param name="password"></param>
		/// <param name="keySize"></param>
		/// <param name="key"></param>
		/// <param name="blockSize"></param>
		/// <param name="iv"></param>
		private static void GenerateKeyFromPassword(string password, int keySize, out byte[] key, int blockSize, out byte[] iv)
		{
			byte[] salt = System.Text.Encoding.UTF8.GetBytes("4249D4C0-CDD6-411E-B26A-F072AC8A8357");
			Rfc2898DeriveBytes deriveBytes = new Rfc2898DeriveBytes(password, salt);
			key = deriveBytes.GetBytes(keySize / 8);
			iv = deriveBytes.GetBytes(blockSize / 8);
		}

		/// <summary>
		/// Minecraftのウィンドウをリサイズする。
		/// </summary>
		public static void ResizeMinecraftWindow()
		{
			Process mcProcess = null;
			var importTask = Task.Factory.StartNew(() =>
			{
				System.Threading.Thread.Sleep(8000);

				//javaで動いてるプロセスを列挙
				foreach (Process process in Process.GetProcessesByName("java"))
				{
					if (Regex.IsMatch(process.MainWindowTitle, "Minecraft"))
					{
						if (mcProcess == null)
						{
							mcProcess = process;
							continue;
						}
						if (mcProcess.StartTime < process.StartTime)
						{
							mcProcess = process;
						}
					}
				}
				if (mcProcess != null)
				{
					Win32API.RECT mcWindowRect = new Win32API.RECT();
					Win32API.RECT mcClientRect = new Win32API.RECT();
					Win32API.GetWindowRect(mcProcess.MainWindowHandle, ref mcWindowRect);
					int mcLeft = mcWindowRect.left;
					int mcTop = mcWindowRect.top;
					Win32API.GetClientRect(mcProcess.MainWindowHandle, ref mcClientRect);
					//クライアント領域からウィンドウサイズを計算する
					int mcWidth = SettingsMain.GetInstance().settingsMain.MinecraftWidth + (mcWindowRect.right - mcWindowRect.left - mcClientRect.right);
					int mcHeight = SettingsMain.GetInstance().settingsMain.MinecraftHeight + (mcWindowRect.bottom - mcWindowRect.top - mcClientRect.bottom);
					Win32API.MoveWindow(mcProcess.MainWindowHandle, mcLeft, mcTop, mcWidth, mcHeight, 1);
					Console.WriteLine(String.Format("Resized MinecraftWindow w{0} h{1}", mcWidth, mcHeight));
				}
			});
		}
	}
}
